<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link href="../css/main.css" media="all" rel="stylesheet" type="text/css" />
<link href="../css/highlight.css" media="all" rel="stylesheet" type="text/css" />
<link href="../css/print.css" media="print" rel="stylesheet" type="text/css" />
<title>第19章 - symfonyの設定ファイルをマスターする</title>
</head>

<body>
<div class="navigation">

<table width="100%">
<tr>
<td width="40%" align="left"><a href="18-Performance.html">前の章</a></td>
<td width="20%" align="center"><a href="index.html">ホーム</a></td>
<td width="40%" align="right"><a href=""></a></td>
</tr>
</table>
<hr/>
</div>

<div>
<a name="chapter.19.mastering.symfonys.configuration.files" id="chapter.19.mastering.symfonys.configuration.files"></a><h1>第19章 - symfonyの設定ファイルをマスターする</h1>

<p>現在あなたはsymfonyをとてもよく理解しています。すでにコアの設計を理解し、新しい隠し機能を見つけるためにコードを徹底的に調べる準備ができています。しかし、独自の要件に適用するためにsymfonyのクラスを拡張するまえに、設定ファイルをもっとよく見ることが必要です。すでに多くの機能はsymfonyに組み込まれ、設定を少し変更すれば有効になります。このことはクラスをオーバーライドしなくてもsymfonyコアのふるまいを調整できることを意味します。この章では設定ファイルとこれらの強力な機能を詳しく説明します。</p>

<div class="toc">
<dl>
<dt><a href="#symfony.settings">19.1. symfonyの設定</a></dt>
<dd><dl>
<dt><a href="#default.modules.and.actions">19.1.1. デフォルトのモジュールとアクション</a></dt>
<dt><a href="#optional.feature.activation">19.1.2. オプション機能の有効</a></dt>
<dt><a href="#feature.configuration">19.1.3. 機能のコンフィギュレーション</a></dt>
<dd><dl>
<dt><a href="#output.escaping.settings">19.1.3.1. 出力エスケーピングの設定</a></dt>
<dt><a href="#routing.settings">19.1.3.2. ルーティングの設定</a></dt>
<dt><a href="#form.validation.settings">19.1.3.3. フォームバリデーションの設定</a></dt>
<dt><a href="#cache.settings">19.1.3.4. キャッシュの設定</a></dt>
<dt><a href="#logging.settings">19.1.3.5. ロギングの設定</a></dt>
<dt><a href="#paths.to.assets">19.1.3.6. アセットへのパス</a></dt>
<dt><a href="#default.helpers">19.1.3.7. デフォルトのヘルパー</a></dt>
<dt><a href="#activated.modules">19.1.3.8. 有効なモジュール</a></dt>
<dt><a href="#character.set">19.1.3.9. 文字集合</a></dt>
<dt><a href="#miscellaneous.configuration">19.1.3.10. そのほかの設定</a></dt>
</dl></dd></dl></dd>
<dt><a href="#extending.the.autoloading.feature">19.2. オートロード機能を拡張する</a></dt>
<dt><a href="#custom.file.structure">19.3. カスタムファイル構造</a></dt>
<dd><dl>
<dt><a href="#the.basic.file.structure">19.3.1. 基本的なファイル構造</a></dt>
<dt><a href="#customizing.the.file.structure">19.3.2. ファイル構造をカスタマイズする</a></dt>
<dt><a href="#modifying.the.project.web.root">19.3.3. Web公開のrootディレクトリの修正</a></dt>
<dt><a href="#linking.to.symfony.libraries">19.3.4. symfonyのライブラリにリンクする</a></dt>
</dl></dd>
<dt><a href="#understanding.configuration.handlers">19.4. コンフィギュレーションハンドラーを理解する</a></dt>
<dd><dl>
<dt><a href="#default.configuration.handlers">19.4.1. デフォルトのコンフィギュレーションハンドラー</a></dt>
<dt><a href="#adding.your.own.handler">19.4.2. 独自ハンドラーを追加する</a></dt>
</dl></dd>
<dt><a href="#controlling.php.settings">19.5. PHPの設定をコントロールする</a></dt>
<dt><a href="#summary">19.6. まとめ</a></dt>
</dl>
</div>
<a name="symfony.settings" id="symfony.settings"></a><h2>symfonyの設定</h2>

<p><code>myapp/config/settings.yml</code>ファイルはおもに<code>myapp</code>アプリケーション用のsymfonyの設定を含みます。前の章でこのファイルから多くの設定の機能をすでに見てきましたが、再度これらを見ることにします。</p>

<p>5章で説明したように、このファイルは環境に依存します。すなわちそれぞれの設定が環境ごとに異なる値をとります。このファイルで定義されたそれぞれのパラメーターは<code>sfConfig</code>クラスを通してPHPクラスの内部からアクセスできることを覚えておいてください。パラメーター名は設定名にプレフィックスの<code>sf_</code>をつけたものです。たとえば、<code>cache</code>パラメーターの値を取得したい場合、必要なことは<code>sfConfig::get('sf_cache')</code>を呼び出すだけです。</p>

<a name="default.modules.and.actions" id="default.modules.and.actions"></a><h3>デフォルトのモジュールとアクション</h3>

<p>ルーティングルールが<code>module</code>パラメーターもしくは<code>action</code>パラメーターを定義していない場合、代わりに<code>settings.yml</code>ファイルからの値が使われます;</p>

<ul>
<li><code>default_module</code>: デフォルトの<code>module</code>リクエストパラメーター。デフォルトは<code>default</code>モジュール。</li>
<li><code>default_action</code>: デフォルトの<code>action</code>リクエストパラメーター。デフォルトは<code>index</code>アクション。</li>
</ul>

<p>symfonyは特殊な状況に対してデフォルトページを用意します。ルーティングエラーの場合、symfonyは<code>default</code>モジュールのアクションを実行します。このアクションは<code>$sf_symfony_data_dir_modules/default/</code>ディレクトリに保存されています。<code>settings.yml</code>ファイルはエラーごとに実行するアクションを定義します:</p>

<ul>
<li><code>error_404_module</code>と<code>error_404_action</code>: ユーザーによって入力されたURLがどのrouteにもマッチしないもしくは<code>sfError404Exception</code>が起動するときに呼び出されるアクションです。デフォルト値は<code>default/error404</code>です。</li>
<li><code>login_module</code>と<code>login_action</code>: <code>security.yml</code>ファイルのなかで<code>secure</code>と定義されたページに認証されていないユーザーがアクセスしようとするときに呼び出されるアクション(詳細は6章を参照)。デフォルト値は<code>default/login</code>です。</li>
<li><code>secure_module</code>と<code>secure_action</code>: ユーザーがアクションから求められるクレデンシャルを持たないときに呼び出されるアクションです。デフォルト値は<code>default/secure</code>です。</li>
<li><code>module_disabled_module</code>と<code>module_disabled_action</code>: ユーザーが<code>module.yml</code>ファイルのなかで無効と宣言されたモジュールをリクエストしたときに呼び出されるアクション。デフォルト値は<code>default/disabled</code>です。</li>
<li><code>unavailable_module</code>と<code>unavailable_action</code>: 無効なアプリケーションからユーザーがページをリクエストしたときに呼び出されるアクション。デフォルト値は<code>default/unavailable</code>です。アプリケーションを無効にするには、<code>settings.yml</code>ファイルのなかで<code>available</code>パラメーターを<code>off</code>に設定してください。</li>
</ul>

<p>アプリケーションを運用サーバーにデプロイするまえにこれらのアクションはカスタマイズすべきです。<code>default</code>モジュールのテンプレートではページにsymfonyのロゴが含まれるからです。これらのページの1つのスクリーンショット、404エラーのページは図19-1をご覧ください。</p>

<p>図19-1 - デフォルトの404エラーページ</p>

<p><img src="images/F1901.jpg" alt="デフォルトの404エラーページ" title="デフォルトの404エラーページ" /></p>

<p>以下の2つの方法でデフォルトのページをオーバーライドできます:</p>

<ul>
<li>アプリケーションの<code>modules/</code>ディレクトリ内で独自の<code>default</code>モジュールを作成し、<code>settings.yml</code>ファイル(<code>index</code>、<code>error404</code>、<code>secure</code>、<code>disabled</code>、と<code>unavailable</code>)と関連するすべてのテンプレート(<code>indexSuccess.php</code>、<code>error404Success.php</code>、<code>loginSuccess.php</code>、<code>secureSuccess.php</code>、<code>disabledSuccess.php</code>と<code>unavailableSuccess.php</code>)内で定義されたすべてのアクションをオーバーライドできます。</li>
<li>アプリケーションのページを使うために<code>settings.yml</code>ファイルのデフォルトのモジュールとアクションの設定を変更できます。</li>
</ul>

<p>ほかの2つのページはsymfonyの見た目を有しており、運用サーバーにデプロイするまえにこれらのページをカスタマイズすることも必要です。これらのページは<code>default</code>モジュールには存在しません。これはsymfonyが適切に動作しないときに呼び出されるからです。代わりに、これらのデフォルトページは<code>$sf_symfony_data_dir/web/errors/</code>ディレクトリのなかで見つかります:</p>

<ul>
<li><code>error500.php</code>: 運用環境で内部のサーバーエラーが起きるときに呼び出されるページ。ほかの環境(<code>SF_DEBUG</code>が<code>true</code>に設定されている)においてエラーが起きるとき、symfonyはすべての実行スタックと明快なエラーメッセージを表示します(詳細は16章を参照)。</li>
<li><code>unavailable.php</code>: キャッシュがクリアされている間(すなわち、symfony の<code>clear-cache</code>タスクを呼び出したときからこのタスクの実行が終了するまでの間)にユーザーがページをリクエストしたときに呼び出されるページ。とても大きなキャッシュを持つシステム上において、キャッシュをクリアする処理は数秒かかる可能性があります。symfonyは部分的にクリアされたキャッシュでリクエストを実行できないので、処理が終わるまえに受理されたリクエストはこのページにリダイレクトされます。</li>
</ul>

<p>これらのページをカスタマイズするには、アプリケーションの<code>web/errors/</code>ディレクトリのなかで<code>error500.php</code>ページと<code>unavailable.php</code>ページを作ります。symfonyは固有のページの代わりにこれらを使うようになります。</p>

<blockquote class="note"><p>
  必要なときにリクエストを<code>unavailable.php</code>ページにリダイレクトするには、アプリケーションの<code>settings.yml</code>のなかで<code>check_lock</code>設定を<code>on</code>にする必要があります。デフォルトではこの設定は無効です。この設定によってすべてのリクエストに対してわずかですがオーバーヘッドが追加されるからです。</p>
</blockquote>

<a name="optional.feature.activation" id="optional.feature.activation"></a><h3>オプション機能の有効</h3>

<p><code>settings.yml</code>ファイルのパラメーターのなかには有効もしくは無効にできるsymfonyのオプション機能をコントロールするものがあります。使わない機能を無効にすることでパフォーマンスが少し押し上げられるので、アプリケーションをデプロイするまえにテーブル19-1に示されている設定の一覧を見直してください。</p>

<p>テーブル 19-1 - <code>settings.yml</code>ファイルを通したオプション機能の一式</p>

<table>
<thead>
<tr>
  <th>パラメーター</th>
  <th>説明</th>
  <th>デフォルト値</th>
</tr>
</thead>
<tbody>
<tr>
  <td><code>use_database</code></td>
  <td>データベースマネージャを有効にする。データベースを使わない場合は<code>off</code>に切り替える。</td>
  <td><code>on</code></td>
</tr>
<tr>
  <td><code>use_security</code></td>
  <td>セキュリティ機能を有効にする(<code>secure</code>アクションとクレデンシャル; 6章を参照)。デフォルトのセキュリティフィルター(<code>sfBasicSecurityFilter</code>)は<code>on</code>の場合のみ有効です。</td>
  <td><code>on</code></td>
</tr>
<tr>
  <td><code>use_flash</code></td>
  <td>flashパラメーター機能を有効にする(6章を参照)。アクション内で<code>set_flash()</code>メソッドを決して使わない場合は<code>off</code>に設定する。flashフィルター(<code>sfFlashFilter</code>)は<code>on</code>になっているときのみ有効。</td>
  <td><code>on</code></td>
</tr>
<tr>
  <td><code>i18n</code></td>
  <td>インターフェイスの翻訳機能を有効にする(13章を参照)。他言語アプリケーションのために<code>on</code>に設定する。</td>
  <td><code>off</code></td>
</tr>
<tr>
  <td><code>logging_enabled</code></td>
  <td>symfonyのイベントのロギング機能を有効にする。<code>logging.yml</code>設定を無視してsymfonyのロギング機能を完全に<code>off</code>に切り替えたいときは<code>off</code>に設定する。</td>
  <td><code>on</code></td>
</tr>
<tr>
  <td><code>escaping_strategy</code></td>
  <td>出力エスケーピング機能の方針を有効にして定義する(7章を参照)。テンプレート内で<code>$sf_data</code>コンテナを使わない場合に<code>off</code>に設定する。</td>
  <td><code>bc</code></td>
</tr>
<tr>
  <td><code>cache</code></td>
  <td>テンプレートキャッシュを有効にする(12章を参照)。モジュールの1つが<code>cache.yml</code>ファイルを含む場合に<code>on</code>に設定する。キャッシュフィルター(<code>sfCacheFilter</code>)が<code>on</code>になっている場合にのみ有効</td>
  <td>開発環境では<code>off</code>、運用環境では<code>on</code></td>
</tr>
<tr>
  <td><code>web_debug</code></td>
  <td>簡単なデバッグのためにWebデバッグツールバーを有効にする(16章を参照)。ツールバーをすべてのページに表示するために<code>on</code>に設定する。Webデバッグフィルター(<code>sfWebDebugFilter</code>)が<code>on</code>のときのみ有効。</td>
  <td><code>on</code>は開発環境、<code>off</code>は運用環境</td>
</tr>
<tr>
  <td><code>check_symfony_version</code></td>
  <td>すべてのリクエストに対してsymfonyのバージョンチェックを有効にする。symfonyをアップグレードした後に自動的にキャッシュをクリアするために<code>on</code>に設定する。アップグレードした後につねにキャッシュをクリアする場合は<code>off</code>のままにしておく。</td>
  <td><code>off</code></td>
</tr>
<tr>
  <td><code>check_lock</code></td>
  <td><code>clear-cache</code>タスクと<code>disable</code>タスクで起動するアプリケーションのロックシステムを有効にする(前のセクションを参照)。無効されたアプリケーションへのリクエストを<code>$sf_symfony_data_dir/web/errors/unavailable.php</code>ページにリダイレクトするにはこのパラメーターを<code>on</code>に設定する。</td>
  <td><code>off</code></td>
</tr>
<tr>
  <td><code>compressed</code></td>
  <td>PHPのレスポンス圧縮機能を有効にする。PHP圧縮ハンドラー経由で出力するHTMLを圧縮するには<code>on</code>にする。</td>
  <td><code>off</code></td>
</tr>
<tr>
  <td><code>use_process_cache</code></td>
  <td>PHPアクセレータに基づいてsymfonyの最適化を有効にする。PHPアクセレータ(たとえば、APC、XCache、eAcceleratorなど)がインストールされたとき、symfonyはリクエスト間でオブジェクトと設定をメモリに保存する機能を利用する。開発環境、もしくはPHPアクセレータ最適化が必要ではない時に<code>off</code>に設定する。アクセレータがインストールされていなくても、<code>on</code>のままにしておいてもパフォーマンスに害をなさないことを留意する</td>
  <td><code>on</code></td>
</tr>
</tbody>
</table>

<a name="feature.configuration" id="feature.configuration"></a><h3>機能のコンフィギュレーション</h3>

<p>symfonyは組み込み機能、たとえば、バリデーション、キャッシュ、サードパーティのモジュールなどのふるまいを変更するにはいくつかの<code>settings.yml</code>ファイルのパラメーターを使います。</p>

<a name="output.escaping.settings" id="output.escaping.settings"></a><h4>出力エスケーピングの設定</h4>

<p>出力エスケーピングの設定は変数がテンプレートにアクセスする方法をコントロールします(7章を参照)。<code>settings.yml</code>ファイルはこの機能のために2つの設定を含みます:</p>

<ul>
<li><code>escaping_strategy</code>設定は<code>bc</code>、<code>both</code>、<code>on</code>、もしくは<code>off</code>の値をとることができます。</li>
<li><code>escaping_method</code>設定は<code>ESC_RAW</code>、<code>ESC_ENTITIES</code>、<code>ESC_JS</code>、もしくは<code>ESC_JS_ENTITIES</code>の値に設定できます。</li>
</ul>

<a name="routing.settings" id="routing.settings"></a><h4>ルーティングの設定</h4>

<p>ルーティングの2つの設定(9章を参照)は<code>settings.yml</code>ファイルに保存されます:</p>

<ul>
<li><code>suffix</code>パラメーターは生成されたURLのためにデフォルトのサフィックスを設定します。デフォルト値はピリオド(<code>.</code>)で、どの接尾辞にも一致しません。たとえば、すべての生成されたURLが静的なページに見えるように<code>.html</code>に設定してください。</li>
<li><code>no_script_name</code>パラメーターは生成されたURLのフロントコントローラー名を有効にします。さまざまなディレクトリでフロントコントローラーを保存し、デフォルトのURL書き換えルールを変更しないかぎり、<code>no_script_name</code>設定はプロジェクトの単独のアプリケーションでのみ<code>on</code>にできます。通常はあなたのメインアプリケーションの運用環境のみ<code>on</code>で他は<code>off</code>です。</li>
</ul>

<a name="form.validation.settings" id="form.validation.settings"></a><h4>フォームバリデーションの設定</h4>

<p>フォームバリデーションの設定は<code>Validation</code>ヘルパーによるエラーメッセージが表示される方法をコントロールします(10章を参照)。これらのエラーは<code>&lt;div&gt;</code>に含まれ、<code>id</code>属性を形成するためにこれらのエラーは<code>validation_error_class</code>設定と<code>validation_error_id_prefix</code>設定を<code>class</code>属性として使います。デフォルト値は<code>form_error</code>と<code>error_for_</code>なので、<code>foobar</code>という名前の入力に対して<code>form_error()</code>ヘルパーへの呼び出しによる属性出力は<code>class="form_error" id="error_for_foobar"</code>になります。</p>

<p>2つの設定はそれぞれのエラーメッセージ: <code>validation_error_prefix</code>と<code>validation_error_suffix</code>の前後に来る文字を決定します。一度にすべてのエラーメッセージをカスタマイズするためにこれらの設定を変更できます。</p>

<a name="cache.settings" id="cache.settings"></a><h4>キャッシュの設定</h4>

<p>キャッシュ設定の大部分は<code>cache.yml</code>ファイルのなかで定義されますが。<code>settings.yml</code>ファイルのなかの以下の2つの設定は異なります。<code>cache</code>はテンプレートキャッシュメカニズムを有効にし、<code>etag</code>はサーバーサイド上のEtagハンドリングを有効にします(15章を参照)。</p>

<a name="logging.settings" id="logging.settings"></a><h4>ロギングの設定</h4>

<p>2つのロギングの設定(16章を参照)は<code>settings.yml</code>ファイルに保存されます:</p>

<ul>
<li><code>error_reporting</code>設定はどのイベントがPHPのログに記録されるのかを指定します。デフォルトでは、運用環境では<code>341</code>に設定され(記録されるイベントは<code>E_PARSE</code>、<code>E_COMPILE_ERROR</code>、<code>E_ERROR</code>、<code>E_CORE_ERROR</code>、と<code>E_USER_ERROR</code>)、開発環境では<code>4095</code>に設定されます(<code>E_ALL</code>と<code>E_STRICT</code>)。</li>
<li><code>web_debug</code>設定はWebデバッグツールバーを有効にします。開発とテスト環境では<code>on</code>に設定します。</li>
</ul>

<a name="paths.to.assets" id="paths.to.assets"></a><h4>アセットへのパス</h4>

<p><code>settings.yml</code>ファイルはアセットへのパスも保存します。symfonyに搭載されたアセット以外の別のバージョンのアセットを使いたい場合、これらのパス設定を変更できます:</p>

<ul>
<li><code>rich_text_js_dir</code>に保存されるリッチなテキストエディタのJavaScriptファイル(デフォルトで<code>js/tiny_mce</code>)</li>
<li><code>prototype_web_dir</code>に保存されるPrototypeライブラリ(デフォルトで<code>/sf/prototype</code>)</li>
<li><code>admin_web_dir</code>に保存されadministrationジェネレーターが必要なファイル</li>
<li><code>web_debug_web_dir</code>に保存されWebデバッグツールバーが必要なファイル</li>
<li><code>calendar_web_dir</code>に保存されJavaScriptのカレンダーが必要なファイル</li>
</ul>

<a name="default.helpers" id="default.helpers"></a><h4>デフォルトのヘルパー</h4>

<p>デフォルトのヘルパーは、すべてのテンプレートに対してロードされ、<code>standard_helpers</code>設定で宣言されます(7章を参照)。デフォルトでは、これらは<code>Partial</code>、<code>Cache</code>、<code>Form</code>ヘルパーグループです。アプリケーションのすべてのテンプレート内部でヘルパーグループを利用する場合、ヘルパーグループの名前を<code>standard_helpers</code>設定に追加すればそれぞれのテンプレート上で<code>use_helper()</code>ヘルパーを用いてヘルパーグループを宣言する煩わしい手続きを行わずにすみます。</p>

<a name="activated.modules" id="activated.modules"></a><h4>有効なモジュール</h4>

<p>プラグインもしくはsymfonyコアから有効にされるモジュールは<code>enabled_modules</code>パラメーターで宣言されます。プラグインがモジュールを搭載する場合、<code>enabled_modules</code>パラメーターで宣言されないかぎりユーザーはこのモジュールをリクエストできません。<code>default</code>モジュールはsymfonyのデフォルトページ(congratulations、page not foundページなど)を提供し、デフォルトで唯一有効なモジュールです。</p>

<a name="character.set" id="character.set"></a><h4>文字集合</h4>

<p>レスポンスの文字集合はアプリケーション全体の設定です。フレームワークの多くのコンポーネントで使われるからです(テンプレート、出力エスケーパ、ヘルパーなど)。定義される<code>charset</code>設定のデフォルト値は<code>utf-8</code>(推奨)です。</p>

<a name="miscellaneous.configuration" id="miscellaneous.configuration"></a><h4>そのほかの設定</h4>

<p><code>settings.yml</code>ファイルはコアのふるまいのためにsymfonyが内部で利用するいくつかのパラメーターを含みます。リスト19-1は設定ファイルに現れるパラメーターの一覧です。</p>

<p>リスト19-1 - そのほかのコンフィギュレーション設定(<code>myapp/config/settings.yml</code>)</p>

<pre><code># symfonyのコアクラスのコメントをcore_compile.ymlファイルで定義されたものとして除去する
strip_comments:         on
# クラスがリクエストされまだロードされていないときに呼び出される関数は
# 呼び出し可能な配列を必要とする。フレームワークブリッジによって使われる
autoloading_functions:  ~
# 秒単位の、セッションのタイムアウト
timeout:                1800
# 例外の起動前のアクションの前のフォワードの最大回数
max_forwards:           5
# グローバル定数
path_info_array:        SERVER
path_info_key:          PATH_INFO
url_format:             PATH
</code></pre>

<blockquote class="sidebar"><p class="title">
  アプリケーションの設定を追加する</p>
  
  <p><code>settings.yml</code>ファイルはアプリケーションに対してsymfonyの設定を定義します。5章で説明したように新しいパラメーターを追加したい場合、最適の場所は<code>myapp/config/app.yml</code>ファイルです。このファイルは環境にも依存しており、このファイルが定義する設定の値は設定名にプレフィックスの<code>app_</code>を付け加えることで<code>sfConfig</code>クラスを通して利用できます。</p>

<pre><code>all:
  creditcards:
    fake:             off    # app_creditcards_fake
    visa:             on     # app_creditcards_visa
    americanexpress:  on     # app_creditcards_americanexpress
</code></pre>
  
  <p>プロジェクトの設定ディレクトリのなかで<code>app.yml</code>ファイルを書くこともできますが、これはカスタムプロジェクト設定を定義する方法を提供します。設定カスケードはこのファイルにも適用するので、アプリケーションの<code>app.yml</code>ファイルで定義された設定はプロジェクトレベルで定義された設定をオーバーライドします。</p>
</blockquote>

<a name="extending.the.autoloading.feature" id="extending.the.autoloading.feature"></a><h2>オートロード機能を拡張する</h2>

<p>オートロード機能は2章で手短に説明しましたが、これによってコードが特定のディレクトリに設置していればクラスをrequireせずにすみます。このことは、必要なときだけ、適切な時点に必要なクラスだけをロードする作業をsymfonyに任せられることを意味します。</p>

<p><code>autoload.yml</code>ファイルはオートロードされたクラスが保存されるパスの一覧を示します。この設定ファイルが最初に処理されたとき、symfonyはこのファイルに参照されたすべてのディレクトリを解析します。<code>.php</code>の拡張子を持つファイルがこれらのディレクトリの1つのなかで見つかるたびに、このファイル内で見つかるファイルパスとクラス名がオートロードクラスの内部リストに追加されます。このリストはキャッシュ、<code>config/config_autoload.yml</code>ファイルに保存されます。それから、実行時に、クラスが使われたとき、symfonyはクラスのパスをこのリストのなかで探し<code>.php</code>ファイルを自動的にインクルードします。</p>

<p>オートロード機能はクラスかつ/またはインターフェイスを含むすべての<code>.php</code>ファイルに対して機能します。</p>

<p>デフォルトでは、つぎのプロジェクトディレクトリに保存されたクラスはオートロード機能からの恩恵を受けます:</p>

<ul>
<li><code>myproject/lib/</code></li>
<li><code>myproject/lib/model</code></li>
<li><code>myproject/apps/myapp/lib/</code></li>
<li><code>myproject/apps/myapp/modules/mymodule/lib</code></li>
</ul>

<p><code>autolaod.yml</code>ファイルはアプリケーションのデフォルトの設定ディレクトリのなかには存在しません。symfonyの設定を修正したい場合、たとえばファイル構造のどこかに保存されたクラスをオートロードするには、空の<code>autoload.yml</code>ファイルを作り、<code>$sf_symfony_data_dir/config/autoload.yml</code>ファイルもしくは独自ファイルの設定をオーバーライドします。</p>

<p><code>autoload.yml</code>ファイルは<code>autoload:</code>キーで始まり、symfonyがクラスを探す場所のリストを記載しなければなりません。それぞれの場所はラベルを必要とします: これによってsymfonyのエントリーをオーバーライドできます。それぞれの位置に対して、<code>name</code>(<code>config_autload.yml.php</code>でコメントとして表示される)と絶対パス(<code>path</code>)を記入してください。それから、検索が再帰的(<code>recursive</code>)であるように定義すると、symfonyはすべてのサブディレクトリで<code>.php</code>ファイルを探します。また望むサブディレクトリを除外(<code>exclude</code>)します。リスト19-2はデフォルトで使われる場所とファイルの構文を示しています。</p>

<p>リスト19-2 - オートロードのデフォルト設定(<code>$sf_symfony_data_dir/config/autoload.yml</code>ファイル)</p>

<pre><code>autoload:

  # symfonyコア
  symfony:
    name:           symfony
    path:           %SF_SYMFONY_LIB_DIR%
    recursive:      on
    exclude:        [vendor]

  propel:
    name:           propel
    path:           %SF_SYMFONY_LIB_DIR%/vendor/propel
    recursive:      on

  creole:
    name:           creole
    path:           %SF_SYMFONY_LIB_DIR%/vendor/creole
    recursive:      on

  propel_addon:
    name:           propel addon
    files:
      Propel:       %SF_SYMFONY_LIB_DIR%/addon/propel/sfPropelAutoload.php

  # プラグイン
  plugins_lib:
    name:           plugins lib
    path:           %SF_PLUGINS_DIR%/*/lib
    recursive:      on

  plugins_module_lib:
    name:           plugins module lib
    path:           %SF_PLUGINS_DIR%/*/modules/*/lib
    prefix:         2
    recursive:      on

  # プロジェクト
  project:
    name:           project
    path:           %SF_LIB_DIR%
    recursive:      on
    exclude:        [model, symfony]

  project_model:
    name:           project model
    path:           %SF_MODEL_LIB_DIR%
    recursive:      on

  # アプリケーション
  application:
    name:           application
    path:           %SF_APP_LIB_DIR%
    recursive:      on

  modules:
    name:           module
    path:           %SF_APP_DIR%/modules/*/lib
    prefix:         1
    recursive:      on
</code></pre>

<p>ルールのパスにワイルドカードを含めることは可能で、<code>constants.php</code>ファイルからファイルパスのパラメーターが使えます(つぎのセクションを参照)。設定ファイルのなかでこれらのパラメーターを使う場合、これらのパラメーターは大文字で始めと終わりを<code>%</code>で挟まなければなりません。</p>

<p>独自の<code>autoload.yml</code>ファイルを編集すれば新しい位置がsymfonyのオートロード機能に追加されますが、このメカニズムを拡張してsymfonyのハンドラーに独自のオートロードハンドラーを追加したいことがあります。これは<code>settings.yml</code>ファイルのなかの<code>autoloading_function</code>パラメーターを通して実現できます。つぎのように、このパラメーターは値として呼び出し可能なクラスの配列を必要とします:</p>

<pre><code>.settings:
  autoloading_functions:
    - [myToolkit, autoload]
</code></pre>

<p>symfonyは新しいクラスに遭遇するとき、最初に独自のオートロードシステムが試されます(そして<code>autoload.yml</code>で定義された位置が使われます)。クラスの定義が見つからない場合、クラスが見つかるまで、<code>settings.yml</code>ファイルからほかのオートロード機能を試します。望む数だけオートロードメカニズムを追加できます。たとえば、ほかのフレームワークコンポーネントへのブリッジを提供するためなどです(17章を参照)。</p>

<a name="custom.file.structure" id="custom.file.structure"></a><h2>カスタムファイル構造</h2>

<p>symfonyフレームワークは何か(コアクラスからテンプレート、プラグイン、設定、など)を探すためにパスを使うたびに、実際のパスの代わりにパス変数を使います。これらの変数を変更することで、symfonyプロジェクトのディレクトリ構造を完全に変更して、顧客のファイル構造の要件に適合させることができます。</p>

<blockquote class="caution"><p>
  symfonyプロジェクトのディレクトリ構造をカスタマイズするのは可能ですが、かならずしもよいアイディアではありません。symfonyのようなフレームワークの強みの一つは。規約が尊重されることでWeb開発者が慣習を尊重して開発されたプロジェクトを見て安心できることです。独自のディレクトリ構造を利用することを決定するまえにかならずこの問題を考えてください。</p>
</blockquote>

<a name="the.basic.file.structure" id="the.basic.file.structure"></a><h3>基本的なファイル構造</h3>

<p>パス変数は、アプリケーションが起動するときに含まれる、<code>$sf_symfony_data_dir/config/constants.php</code>ファイルのなかで定義されます。これらの変数は<code>sfConfig</code>オブジェクトに保存されるのでオーバーライドするのは簡単です。リスト19-3はこれらが参照するパス変数とディレクトリのリストを示しています。</p>

<p>リスト19-3 - デフォルトのファイル構造の変数(<code>$sf_symfony_data_dir/config/constants.php</code>)</p>

<pre><code>sf_root_dir           # myproject/
                      #   apps/
sf_app_dir            #     myapp/
sf_app_config_dir     #       config/
sf_app_i18n_dir       #       i18n/
sf_app_lib_dir        #       lib/
sf_app_module_dir     #       modules/
sf_app_template_dir   #       templates/
sf_bin_dir            #   batch/
                      #   cache/
sf_base_cache_dir     #     myapp/
sf_cache_dir          #       prod/
sf_template_cache_dir #         templates/
sf_i18n_cache_dir     #         i18n/
sf_config_cache_dir   #         config/
sf_test_cache_dir     #         test/
sf_module_cache_dir   #         modules/
sf_config_dir         #   config/
sf_data_dir           #   data/
sf_doc_dir            #   doc/
sf_lib_dir            #   lib/
sf_model_lib_dir      #     model/
sf_log_dir            #   log/
sf_test_dir           #   test/
sf_plugins_dir        #   plugins/
sf_web_dir            #   web/
sf_upload_dir         #     uploads/
</code></pre>

<p>重要なディレクトリへのすべてのパスは<code>_dir</code>で終わるパラメーターによって決定されます。あとで必要なときにパスを変更できるように、本当の(相対もしくは絶対)ファイルパスの代わりにパス変数をつねに使用してください。たとえば、ファイルをアプリケーションの<code>uploads/</code>ディレクトリに移動させたいとき、パスとして<code>SF_ROOT_DIR.'/web/uploads/'</code>の代わりに<code>sfConfig::get('sf_upload_dir')</code>を使います。</p>

<p>ルーティングシステムがモジュールの名前(<code>$module_name</code>)を定義するとき、モジュールのディレクトリ構造は実行時に定義されます。リスト19-4で示されるように、<code>constants.php</code>ファイルのなかで定義されたパス名にしたがって、ディレクトリは自動的に作成されます。</p>

<p>リスト19-4 - モジュールのファイル構造のデフォルトの変数</p>

<pre><code>sf_app_module_dir                 # modules/
module_name                       #  mymodule/
sf_app_module_action_dir_name     #    actions/
sf_app_module_template_dir_name   #    templates/
sf_app_module_lib_dir_name        #    lib/
sf_app_module_view_dir_name       #    views/
sf_app_module_validate_dir_name   #    validate/
sf_app_module_config_dir_name     #    config/
sf_app_module_i18n_dir_name       #    i18n/
</code></pre>

<p>ですので、たとえば、現在のモジュールの<code>validate/</code>ディレクトリへのパスは実行時に作成されます:</p>

<pre class="php">sfConfig<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st_h">'sf_app_module_dir'</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st_h">'/'</span><span class="sy0">.</span><span class="re0">$module_name</span><span class="sy0">.</span><span class="st_h">'/'</span><span class="sy0">.</span>sfConfig<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st_h">'sf_app_module_validate_dir_name'</span><span class="br0">&#41;</span></pre>

<a name="customizing.the.file.structure" id="customizing.the.file.structure"></a><h3>ファイル構造をカスタマイズする</h3>

<p>アプリケーションを開発するさいに、顧客がすでにディレクトリ構造を定義しており、symfonyのロジックに適合させるために構造を変更する意志のない場合、おそらくデフォルトのプロジェクトファイル構造を修正する必要があります。<code>sfConfig</code>オブジェクトで<code>sf_XXX_dir</code>変数と<code>sf_XXX_dir_name</code>変数をオーバーライドすることで、デフォルトとはまったく異なるディレクトリ構造でsymfonyを動かすことができます。これを行う最適の場所はアプリケーションの<code>config.php</code>ファイルです。</p>

<blockquote class="caution"><p>
  <code>sfConfig</code>オブジェクトで<code>sf_XXX_dir</code>変数と<code>sf_XXX_dir_name</code>変数をオーバーライドするには、プロジェクトではなくアプリケーションの<code>config.php</code>を使います。プロジェクトの<code>config/config.php</code>ファイルは、<code>sfConfig</code>クラスがまだ存在せず<code>config/constants.php</code>ファイルがロードされていない、リクエスト期間の初期の段階でロードされます。</p>
</blockquote>

<p>たとえば、すべてのアプリケーションにテンプレートのレイアウト用に1つの共通ディレクトリを共有させたい場合、<code>sf_template_dir</code>設定をオーバーライドするには以下の行を<code>myapp/config/config.php</code>ファイルに追加します:</p>

<pre class="php">sfConfig<span class="sy0">::</span><span class="me2">set</span><span class="br0">&#40;</span><span class="st_h">'sf_app_template_dir'</span><span class="sy0">,</span> sfConfig<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st_h">'sf_root_dir'</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="kw4">DIRECTORY_SEPARATOR</span><span class="sy0">.</span><span class="st_h">'templates'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre>

<p>アプリケーションの<code>config.php</code>ファイルは空ではないので、このファイルでファイル構造の定義を格納する必要がある場合、ファイルの終わりの部分でこの作業を行うように注意してください。</p>

<a name="modifying.the.project.web.root" id="modifying.the.project.web.root"></a><h3>Web公開のrootディレクトリの修正</h3>

<p><code>constants.php</code>ファイルに組み込まれたすべてのパスはプロジェクトのrootディレクトリに依存します。このディレクトリパスはフロントコントローラー(<code>SF_ROOT_DIR</code>)によって定義されます。通常のrootディレクトリは<code>web/</code>ディレクトリの上のレベルですが、異なる構造を利用できます。メインのディレクトリ構造が2つのディレクトリから構成される場合を考えてみます。リスト19-5で示されるように、1つのディレクトリは公開領域で、もう1つのディレクトリは非公開領域に存在します。プロジェクトを共用ホスティングサービス上でホストするときにこのコンフィギュレーションを選ぶことはよくあります。</p>

<p>リスト19-5 - 共用サーバーのためのカスタムディレクトリ構造の例</p>

<pre><code>symfony/    # 非公開領域
  apps/
  batch/
  cache/
  ...
www/        # 公開領域
  images/
  css/
  js/
  index.php
</code></pre>

<p>この場合、rootディレクトリは<code>symfony/</code>ディレクトリです。ですので、アプリケーションを動かすには<code>index.php</code>フロントコントローラーは<code>SF_ROOT_DIR</code>をつぎのように定義する必要があるだけです:</p>

<pre class="php"><span class="kw3">define</span><span class="br0">&#40;</span><span class="st_h">'SF_ROOT_DIR'</span><span class="sy0">,</span> <span class="kw3">dirname</span><span class="br0">&#40;</span><span class="kw4">__FILE__</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st_h">'/../symfony'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre>

<p>加えて、公開領域は通常の<code>web/</code>ディレクトリの代わりに<code>www/</code>ディレクトリで、つぎのように、アプリケーションの<code>config.php</code>ファイルのなかで2つのファイルパスをオーバーライドしなければなりません:</p>

<pre class="php">sfConfig<span class="sy0">::</span><span class="me2">add</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span>
  <span class="st_h">'sf_web_dir'</span>      <span class="sy0">=&gt;</span> SF_ROOT_DIR<span class="sy0">.</span><span class="st_h">'/../www'</span><span class="sy0">,</span>
  <span class="st_h">'sf_upload_dir'</span>   <span class="sy0">=&gt;</span> SF_ROOT_DIR<span class="sy0">.</span><span class="st_h">'/../www/'</span><span class="sy0">.</span>sfConfig<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st_h">'sf_upload_dir_name'</span><span class="br0">&#41;</span><span class="sy0">,</span>
<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre>

<a name="linking.to.symfony.libraries" id="linking.to.symfony.libraries"></a><h3>symfonyのライブラリにリンクする</h3>

<p>リスト19-6で見ることができるように、symfonyのファイルへのパスはプロジェクトの<code>config.php</code>ファイルで定義されます。</p>

<p>リスト19-6 - symfonyライブラリへのパス(<code>myproject/config/config.php</code>)</p>

<pre class="php"><span class="kw2">&lt;?php</span>
&nbsp;
<span class="co1">// symfonyのディレクトリ</span>
<span class="re0">$sf_symfony_lib_dir</span>  <span class="sy0">=</span> <span class="st_h">'/path/to/symfony/lib'</span><span class="sy0">;</span>
<span class="re0">$sf_symfony_data_dir</span> <span class="sy0">=</span> <span class="st_h">'/path/to/symfony/data'</span><span class="sy0">;</span></pre>

<p><code>symfony init-project</code>タスクをコマンドラインから呼び出すとき、これらのパスは初期化されプロジェクトを作成するために使われるsymfonyの設置ディレクトリを参照します。これらはコマンドラインとMVCアーキテクチャの両方から利用されます。</p>

<p>このことはフレームワークファイルへのパスを変更することでsymfonyの別の設置ディレクトリに切り替えることが可能であることを意味します。</p>

<p>これらのパスは絶対パスですが、<code>dirname(__FILE__)</code>を利用することで、プロジェクト構造内部のファイルを参照しプロジェクトを設置するために選ばれたディレクトリの独立性を保つことができます。たとえば、つぎのコードのように、多くのプロジェクトがsymfonyの<code>lib/</code>ディレクトリをプロジェクトの<code>lib/symfony/</code>ディレクトリのシンボリックリンクとして設定し、<code>data/</code>ディレクトリに対しても同じような設定を行います:</p>

<pre><code>myproject/
  lib/
    symfony/ =&gt; /path/to/symfony/lib
  data/
    symfony/ =&gt; /path/to/symfony/data
</code></pre>

<p>この場合、プロジェクトの<code>config.php</code>ファイルはつぎのようにsymfonyのディレクトリを定義する必要があるだけです:</p>

<pre class="php"><span class="re0">$sf_symfony_lib_dir</span>  <span class="sy0">=</span> <span class="kw3">dirname</span><span class="br0">&#40;</span><span class="kw4">__FILE__</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st_h">'/../lib/symfony'</span><span class="sy0">;</span>
<span class="re0">$sf_symfony_data_dir</span> <span class="sy0">=</span> <span class="kw3">dirname</span><span class="br0">&#40;</span><span class="kw4">__FILE__</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st_h">'/../data/symfony'</span><span class="sy0">;</span></pre>

<p>プロジェクトの<code>lib/vendor/</code>ディレクトリ内でsymfonyのファイルを<code>svn:externals</code>プロパティとして格納すること選んだ場合にも同じ原則があてはまります:</p>

<pre><code>myproject/
  lib/
    vendor/
      svn:externals symfony http://svn.symfony-project.com/branches/1.0
</code></pre>

<p>この場合、<code>config.php</code>ファイルはつぎのようになります:</p>

<pre class="php"><span class="re0">$sf_symfony_lib_dir</span>  <span class="sy0">=</span> <span class="kw3">dirname</span><span class="br0">&#40;</span><span class="kw4">__FILE__</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st_h">'/../lib/vendor/symfony/lib'</span><span class="sy0">;</span>
<span class="re0">$sf_symfony_data_dir</span> <span class="sy0">=</span> <span class="kw3">dirname</span><span class="br0">&#40;</span><span class="kw4">__FILE__</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st_h">'/../lib/vendor/symfony/data'</span><span class="sy0">;</span></pre>

<blockquote class="tip"><p>
  アプリケーションを稼働させているサーバーが異なる場合symfonyのライブラリへのパスが異なることがあります。これを有効にする1つの方法は(<code>rsync_exclude.txt</code>に追加することで)プロジェクトの<code>config.php</code>ファイルを同期化の対象から除外することです。ほかの方法は<code>config.php</code>ファイルの開発バージョンと運用バージョンで同じパスを保つことですが、シンボリックリンクを指し示すこれらのパスがサーバーによって変わる可能性があります。</p>
</blockquote>

<a name="understanding.configuration.handlers" id="understanding.configuration.handlers"></a><h2>コンフィギュレーションハンドラーを理解する</h2>

<p>それぞれの設定ファイルはハンドラーを持ちます。コンフィギュレーションハンドラー(configuration handler)の仕事は設定カスケードを管理することと、実行時に設定ファイルを最適化して実行可能なPHPコードに変換することです。</p>

<a name="default.configuration.handlers" id="default.configuration.handlers"></a><h3>デフォルトのコンフィギュレーションハンドラー</h3>

<p>デフォルトのハンドラー設定は<code>$sf_symfony_data_dir/config/config_handlers.yml</code>ファイルに保存されます。このファイルはファイルパスにしたがってハンドラーを設定ファイルにリンクします。リスト19-7はこのファイルの内容を抜粋したものです。</p>

<p>リスト19-7 - <code>$sf_symfony_data_dir/config/config_handlers.yml</code>ファイルの抜粋</p>

<pre><code>config/settings.yml:
  class:    sfDefineEnvironmentConfigHandler
  param:
    prefix: sf_

config/app.yml:
  class:    sfDefineEnvironmentConfigHandler
  param:
    prefix: app_

config/filters.yml:
  class:    sfFilterConfigHandler

modules/*/config/module.yml:
  class:    sfDefineEnvironmentConfigHandler
  param:
    prefix: mod_
    module: yes
</code></pre>

<p>それぞれの設定ファイルに対して(<code>config_handlers.yml</code>ファイルはワイルドカードを持つファイルパスでそれぞれのファイルを識別する)、ハンドラークラスは<code>class</code>キーの下で指定されます。</p>

<p><code>sfDefineEnvironmentConfigHandler</code>クラスによって処理される設定ファイルの設定は<code>sfConfig</code>クラス経由でコードのなかで直接利用できるようになり、<code>param</code>キーはプレフィックスの値を含みます。</p>

<p>設定ファイルを処理するために使われるハンドラーの追加もしくは修正ができます。たとえば、YAMLファイルの代わりに<code>INI</code>ファイルもしくは<code>XML</code>ファイルを使うためです。</p>

<blockquote class="note"><p>
  <code>config_handlers.yml</code>ファイル用のコンフィギュレーションハンドラーは<code>sfRootConfigHandler</code>クラスで、あきらかに変更できません。</p>
</blockquote>

<p>設定の解析方法を修正する必要がある場合、アプリケーションの<code>cofig/</code>フォルダー内に空の<code>config_handlers.yml</code>ファイルを作り、<code>class</code>キーの行を書いたクラスでオーバーライドします。</p>

<a name="adding.your.own.handler" id="adding.your.own.handler"></a><h3>独自ハンドラーを追加する</h3>

<p>設定ファイルを処理するハンドラーを利用することで2つの大きな利点がもたらされます:</p>

<ul>
<li>設定ファイルはPHPの実行コードに変換され、このコードはキャッシュに保存されます。このことは、運用環境において設定は1回だけ解析されるのでパフォーマンスが最適化されていることを意味します。</li>
<li>設定ファイルは異なるレベル(プロジェクトとアプリケーション)で定義することが可能で、最後のパラメーターの値はカスケードから由来します。プロジェクトレベルでパラメーターを定義し、アプリケーション単位でこれらをオーバーライドできます。</li>
</ul>

<p>独自のコンフィギュレーションハンドラーを書きたい場合、<code>$sf_symfony_lib_dir/config/</code>ディレクトリのなかでsymfonyによって使われる構造の例にしたがってください。</p>

<p>アプリケーションが<code>myMapAPI</code>クラスを含む場合を考えてみましょう。<code>myMapAPI</code>クラスは地図を配信するサードパーティのサービスのためのインターフェイスを提供します。リスト19-8で示されるように、このクラスはURLとユーザー名で初期化することが必要です。</p>

<p>リスト19-8 - <code>myMapAPI</code>クラスの初期化の例</p>

<pre class="php"><span class="re0">$mapApi</span> <span class="sy0">=</span> <span class="kw2">new</span> myMapAPI<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$mapApi</span><span class="sy0">-&gt;</span><span class="me1">setUrl</span><span class="br0">&#40;</span><span class="re0">$url</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$mapApi</span><span class="sy0">-&gt;</span><span class="me1">setUser</span><span class="br0">&#40;</span><span class="re0">$user</span><span class="br0">&#41;</span><span class="sy0">;</span></pre>

<p>アプリケーションの<code>config/</code>ディレクトリ内に設置された、<code>map.yml</code>という名前のカスタム設定ファイルでこれら2つのパラメーターを保存するとよいでしょう。この設定ファイルはつぎのような内容を含むことがあります:</p>

<pre><code>api:
  url:  map.api.example.com
  user: foobar
</code></pre>

<p>これらの設定をリスト19-8と同等なコードに変換するために、コンフィギュレーションハンドラーを作成しなければなりません。それぞれのコンフィギュレーションハンドラーは<code>sfConfigHandler</code>クラスを拡張し<code>execute()</code>メソッドを提供しなければなりません。<code>execute()</code>メソッドはパラメーターとして設定ファイルへのファイルパスの配列が必要で、キャッシュファイルに書き込まれるデータを返さなければなりません。YAMLファイル用のハンドラーは<code>sfYamlConfigHandler</code>クラスを拡張します。このクラスはYAMLパーサーのために追加のファシリティを提供します。<code>map.yml</code>ファイルに対する典型的なコンフィギュレーションハンドラーはリスト19-9で示されるように書けます。</p>

<p>リスト19-9 - カスタムコンフィギュレーションハンドラー(<code>myapp/lib/myMapConfigHandler.class.php</code>)</p>

<pre class="php"><span class="kw2">&lt;?php</span>
&nbsp;
<span class="kw2">class</span> myMapConfigHandler <span class="kw2">extends</span> sfYamlConfigHandler
<span class="br0">&#123;</span>
  <span class="kw2">public</span> <span class="kw2">function</span> execute<span class="br0">&#40;</span><span class="re0">$configFiles</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">initialize</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="co1">// yamlを解析する</span>
    <span class="re0">$config</span> <span class="sy0">=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">parseYamls</span><span class="br0">&#40;</span><span class="re0">$configFiles</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="re0">$data</span>  <span class="sy0">=</span> <span class="st0">&quot;&lt;?php<span class="es1">\n</span>&quot;</span><span class="sy0">;</span>
    <span class="re0">$data</span> <span class="sy0">.=</span> <span class="st0">&quot;<span class="es1">\$</span>mapApi = new myMapAPI();<span class="es1">\n</span>&quot;</span><span class="sy0">;</span>
&nbsp;
    <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">isset</span><span class="br0">&#40;</span><span class="re0">$config</span><span class="br0">&#91;</span><span class="st_h">'api'</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st_h">'url'</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
      <span class="re0">$data</span> <span class="sy0">.=</span> <span class="kw3">sprintf</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es1">\$</span>mapApi-&gt;setUrl('<span class="es6">%s</span>');<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> <span class="re0">$config</span><span class="br0">&#91;</span><span class="st_h">'api'</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st_h">'url'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">isset</span><span class="br0">&#40;</span><span class="re0">$config</span><span class="br0">&#91;</span><span class="st_h">'api'</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st_h">'user'</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
      <span class="re0">$data</span> <span class="sy0">.=</span> <span class="kw3">sprintf</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es1">\$</span>mapApi-&gt;setUser('<span class="es6">%s</span>');<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> <span class="re0">$config</span><span class="br0">&#91;</span><span class="st_h">'api'</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st_h">'user'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="kw1">return</span> <span class="re0">$data</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre>

<p>symfonyが<code>execute()</code>メソッドに渡す<code>$configFiles</code>配列は<code>config/</code>フォルダーのなかで見つかるすべての<code>map.yml</code>ファイルへのパスを格納します。<code>parseYamls()</code>メソッドは設定カスケードを扱います。</p>

<p>この新しいハンドラーを<code>map.yml</code>ファイルと関連づけるには、つぎのような内容を持つ<code>config_handlers.yml</code>設定ファイルを作成しなければなりません:</p>

<pre><code>config/map.yml:
  class: myMapConfigHandler
</code></pre>

<blockquote class="note"><p>
  クラス(<code>class</code>)はオートロードする(上記の例)かファイルパスが<code>param</code>キーの元の<code>file</code>パラメーターで指定されたファイルのなかで定義しなければなりません。</p>
</blockquote>

<p>アプリケーション内部で<code>map.yml</code>ファイルに基づき<code>myMapConfigHandler</code>ハンドラーによって生成されたコードが必要な場合、つぎの行を呼び出してください:</p>

<pre class="php"><span class="kw1">include</span><span class="br0">&#40;</span>sfConfigCache<span class="sy0">::</span><span class="me2">getInstance</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">checkConfig</span><span class="br0">&#40;</span>sfConfig<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st_h">'sf_app_config_dir_name'</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st_h">'/map.yml'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre>

<p><code>checkConfig()</code>メソッドを呼び出すとき、<code>map.yml.php</code>ファイルがキャッシュにまだ存在しないもしくは<code>map.yml</code>ファイルがキャッシュよりも新しい場合、symfonyは設定ディレクトリのなかの既存の<code>map.yml</code>ファイルを探し<code>config_handlers.yml</code>ファイルで指定されたハンドラーを利用してこれらのファイルを処理します。</p>

<blockquote class="tip"><p>
  YAMLの設定ファイル内部で環境を扱いたい場合、ハンドラーは<code>sfYamlConfigHandler</code>クラスの代わりに<code>sfDefineEnvironmentConfigHandler</code>クラスを拡張できます。設定を読みとるために<code>parseYaml()</code>メソッドを呼び出した後に、<code>mergeEnvironment()</code>メソッドを呼び出します。<code>$config = $this-&gt;mergeEnvironment($this-&gt;parseYamls ($configFiles));</code>を呼び出すことですべての内容を1行で実現できます。</p>
</blockquote>

<p>-</p>

<blockquote class="sidebar"><p class="title">
  既存のコンフィギュレーションハンドラーを利用する</p>
  
  <p>ユーザーが<code>sfConfig</code>クラス経由でコードから値を読みとることができるようにする必要があるだけなら、<code>sfDefineEnvironmentConfigHandler</code>コンフィギュレーションハンドラークラスを利用できます。たとえば、<code>url</code>と<code>user</code>パラメーターをそれぞれ<code>sfConfig::get('map_url')</code>と<code>sfConfig::get('map_user')</code>として利用できるようにするには、ハンドラーをつぎのように定義します:</p>

<pre><code>config/map.yml:
  class: sfDefineEnvironmentConfigHandler
  param:
    prefix: map_
</code></pre>
  
  <p>ほかのハンドラーによってすでに使われているプレフィックスを選ばないように気をつけてください。 既存のプレフィックスは<code>sf_</code>、<code>app</code>、と<code>mod_</code>です。</p>
</blockquote>

<a name="controlling.php.settings" id="controlling.php.settings"></a><h2>PHPの設定をコントロールする</h2>

<p>アジャイル開発のルールとベストプラクティスと互換性のあるPHPの環境を保つために、symfonyは<code>php.ini</code>設定ファイルのいくつかの設定を確認してオーバーライドします。これが<code>php.yml</code>ファイルの目的です。リスト19-10はデフォルトの<code>php.yml</code>ファイルを示します。</p>

<p>リスト19-10 - symfonyのためのPHPのデフォルト設定(<code>$sf_symfony_data_dir/config/php.yml</code>)</p>

<pre><code>set:
  magic_quotes_runtime:        off
  log_errors:                  on
  arg_separator.output:        |
    &amp;amp;

check:
  zend.ze1_compatibility_mode: off

warn:
  magic_quotes_gpc:            off
  register_globals:            off
  session.auto_start:          off
</code></pre>

<p>このファイルの主な目的はPHPの設定がアプリケーションと互換性があることを確認するためです。運用サーバーと同様に可能なかぎり、開発サーバーの設定を確認するためにも非常に便利です。プロジェクトの最初に運用サーバーの設定を検査し、PHPの設定をプロジェクトの<code>php.yml</code>ファイルに報告するのはそういうわけです。これによってプロジェクトを運用のプラットフォームにデプロイしてもいかなる互換性の問題に遭遇しないという信頼感を持って開発とテストを行うことができます。</p>

<p><code>set</code>ヘッダーのもとで定義された変数は修正されます(サーバーの<code>php.ini</code>ファイルでどのように定義されていても)。<code>warn</code>カテゴリのもとで定義された変数はすぐに修正できませんが、これが適切に設定されていなくてもsymfonyは動きます。これらの設定をオンにすることはわるい習慣として見なされているので、この場合symfonyは警告を記録します。<code>check</code>カテゴリのもとで定義された変数は同じようにすぐに修正できませんが、symfonyを動かすためにこれらの変数は特定の値を持たなければなりません。ですので、この場合、<code>php.ini</code>ファイルが正しくなければ、例外が起こります。</p>

<p>symfonyのプロジェクトでエラーを追跡できるようにデフォルトの<code>php.yml</code>ファイルは<code>log_errors</code>ディレクティブを<code>on</code>に設定します。セキュリティの欠陥を防ぐために<code>register_globals</code>ディレクティブを<code>off</code>に設定することも推奨します。</p>

<p>これらの設定をsymfonyに適用したくない、もしくは<code>magic_quotes_gpc</code>ディレクティブと<code>register_globals</code>ディレクティブを<code>on</code>にして警告なしでプロジェクトを動かしたい場合、 アプリケーションの<code>config/</code>ディレクトリ内で<code>php.yml</code>ファイルを作り、変更したいディレクティブの値をオーバーライドしてください。</p>

<p>プロジェクトがPHPの追加の拡張機能を必要な場合、<code>extensions</code>カテゴリのもとで指定できます。つぎのように、このカテゴリは拡張機能の名前の配列を必要とします:</p>

<pre><code>extensions: [gd, mysql, mbstring]
</code></pre>

<a name="summary" id="summary"></a><h2>まとめ</h2>

<p>設定ファイル(configuration file)はsymfonyフレームワークの動作方法を大いに変更します。symfonyはコア機能とファイルの読み込みでさえも設定に依存するので、標準の専用ホストよりも多くの環境に適用できます。このすばらしい設定の柔軟性はsymfonyの主要な強さの1つです。設定ファイルのなかで学ぶべきたくさんの規約を見た初心者を怖がらせることがあるにせよ、このことによってsymfony製のアプリケーションは膨大な数のプラットフォーム、環境に対して、互換性があります。ひとたびsymfonyの設定を習得したら、あなたのアプリケーションを動かすことを拒むサーバーは存在しないでしょう。</p>
</div>
<div class="navigation">
<hr/>
<table width="100%">
<tr>
<td width="40%" align="left"><a href="18-Performance.html">前の章</a></td>
<td width="20%" align="center"><a href="index.html">ホーム</a></td>
<td width="40%" align="right"><a href=""></a></td>
</tr>
</table>

</div>
</body>

</html>
